
from saas.log import *
import hashlib
import time
from Crypto.Cipher import AES
import operator


def pkt_gen_key( secret , time_adjust ):
	tdata = time.gmtime( time.time() + time_adjust )
	return '%s%04d%02d%02d%02d%02d%02d' % ( secret , tdata[0] , tdata[1] , tdata[2] , tdata[3] , tdata[4] , tdata[5] )


def pkt_encrypt( pkt , conf ):
	logm( LOG_DEBUG , 'pkt_encrypt():  encrypting %d bytes of data' % ( len( pkt ) ) )
	if ( len( pkt ) % 16 ) != 0:
		## we gotta add some padding to the end of this mofo.
		extra = 16 - ( len( pkt ) % 16 )
		while ( extra > 0 ):
			pkt += '\0'
			extra -= 1

	## the key source is the same for all encryption methods.
	key = pkt_gen_key( conf.client_secret , conf.time_adjust )

	if conf.enc_type == SAAS_ENC_TYPE_AES256ECB_SHA256:
		aes = AES.new( sha256( key ) , AES.MODE_ECB )
		return aes.encrypt( pkt )
	elif conf.enc_type == SAAS_ENC_TYPE_AES256CBC_SHA256:
		aes = AES.new( sha256( key ) , AES.MODE_CBC )
		return aes.encrypt( pkt )
	if conf.enc_type == SAAS_ENC_TYPE_AES128ECB_SHA256XOR:
		key = sha256( key )
		key = operator.xor( key[0:15] , key[16:31] )
		aes = AES.new( key , AES.MODE_ECB )
		return aes.encrypt( pkt )
	elif conf.enc_type == SAAS_ENC_TYPE_AES128CBC_SHA256XOR:
		key = sha256( key )
		key = operator.xor( key[0:15] , key[16:31] )
		aes = AES.new( key , AES.MODE_CBC )
		return aes.encrypt( pkt )

	return None


def _try_decrypt( pkt , conf , time_offset ):
	return AES.new( sha256( pkt_gen_key( conf.client_secret , conf.time_adjust + time_offset ) ) , AES.MODE_ECB ).decrypt( pkt )


def pkt_decrypt( pkt , conf ):
	offsets = [ 0 , +1 , -1 ]
	for offset in offsets:
		out = _try_decrypt( pkt , conf , offset )
		if out[32:36].encode('hex') == '29c20fc1':
			return out
	return None


def sha256( data ):
	## produce a sha256 hash on-the-spot.
	sha = hashlib.sha256()
	sha.update( data )
	return sha.digest()


def valid512hash( hash512 ):
	if len( hash512 ) != 64:
		return False
	return True

